package com.rtx.wms.std.handler.so.mid;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.rtx.edi.model.api.bo.ApiMappingInfoBo;
import com.rtx.model.dto.edi.EdiInnerRequestDTO;
import com.rtx.model.emums.SysNumberType;
import com.rtx.wms.std.common.bean.Codelkup;
import com.rtx.wms.std.common.bean.WmsConstant;
import com.rtx.wms.std.common.service.CommonService;
import com.rtx.wms.std.ctclass.ClassHolder;
import com.rtx.wms.std.sku.bean.po.Sku;
import com.rtx.wms.std.so.bean.ApiOrderdetail;
import com.rtx.wms.std.so.bean.ApiOrders;
import com.rtx.wms.std.so.bean.Orderdetail;
import com.rtx.wms.std.so.bean.Orders;
import com.rtx.wms.std.so.service.ApiOrdersService;
import com.rtx.wms.std.so.service.OrdersService;
import com.rtx.wms.std.validation.so.OrdersValidation;

import cn.hutool.core.util.StrUtil;

/**
 * 出库单中间表
 */
@Component
public class MidOrdersHandler {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ApiOrdersService apiOrdersService;

    @Autowired
    private OrdersService ordersService;

    @Autowired
    private CommonService commonService;
    
    @Autowired
    protected OrdersValidation ordersValidation;

    /**
     * 出库单从中间表写入WMS
     * @param whseid
     */
    public void handlerMidToWms(String whseid,ApiMappingInfoBo bo){
        //获取中间表未处理成功的订单
        List<ApiOrders> ordersList = selectApiOrders("ris_edi",bo);
        if(CollectionUtils.isEmpty(ordersList)){
            return;
        }
        for(ApiOrders o : ordersList){
            //添加wms出库单
            addWmsOrders(whseid,o,bo);
            //更新中间表状态
            updateApiOrders("ris_edi",o);
        }
    }

    /**
     * 更新中间表
     * @param whseid
     * @param apiOrders
     */
    private void updateApiOrders(String whseid,ApiOrders apiOrders) {
        LambdaUpdateWrapper<ApiOrders> update = Wrappers.lambdaUpdate();
        update.eq(ApiOrders::getSerialkey,apiOrders.getSerialkey())
                .set(ApiOrders::getEdiflag,apiOrders.getEdiflag())
                .set(StringUtils.hasText(apiOrders.getEdimsg()),ApiOrders::getEdimsg,StrUtil.sub(apiOrders.getEdimsg(),0,200))
                .set(ApiOrders::getRtxqueue,apiOrders.getRtxqueue() + 1);
        apiOrdersService.updateByWrapper(whseid,update);
    }

    /**
     * 添加wms出库单
     * @param whseid
     * @param apiOrders
     */
    void addWmsOrders(String whseid,ApiOrders apiOrders,ApiMappingInfoBo bo){
        try {
            Orders orders = convertOrders(whseid,apiOrders,bo);
            //匹配出库单类型
            mappingOrderType(WmsConstant.ENTERPRISE,orders);
            //匹配承运商代码
            carriercodeMapping(whseid,orders,apiOrders.getCarriercode());
            //更据外部单号处理存在的订单
            ordersService.handlerExistsOrders(whseid,orders.getExternorderkey());
            //新增出库单
            ordersService.addOrders(whseid,orders,bo);
            apiOrders.setEdiflag(WmsConstant.SUCCESS_FLAG);
        } catch (Exception e) {
            logger.error("仓库{}，批次号{}从中间表写入WMS异常",whseid,apiOrders.getBatchid(),e);
            apiOrders.setEdiflag(WmsConstant.FAIL_FLAG);
            apiOrders.setEdimsg(e.getMessage());
        }
    }
    
    
    /**
             * 匹配出库单类型
     * @param wmwhseid
     * @param orders
     */
    private void mappingOrderType(String wmwhseid,Orders orders) {
    	String qmtype = orders.getType();
    	orders.setType(qmtype);
//    	Codelkup soTypeMapping =Optional.ofNullable(commonService.selectCodelkupByCodeAndListname(wmwhseid, qmtype, "ORDERTYPE")).orElse(new Codelkup()) ;
//    	if(StringUtils.hasLength(soTypeMapping.getUdf1())) {
//    		orders.setType(soTypeMapping.getUdf1());
//    	}
    }

    /**
     * 获取中间表未处理成功的订单
     * @param whseid
     * @return
     */
    private List<ApiOrders> selectApiOrders(String whseid,ApiMappingInfoBo bo) {
        //获取中间表未处理成功的订单
        QueryWrapper<ApiOrders> query = Wrappers.query();
        query.in("ediflag", Arrays.asList(WmsConstant.DEFAULT_FLAG,WmsConstant.FAIL_FLAG,WmsConstant.FAIL_FLAG_2))
                .lt("rtxqueue",30)
                .last("limit 500");
        return apiOrdersService.selectApiOrdersByWrapper(whseid, query,bo);
    }

    /**
     * 转化类型
     * @param o
     * @return
     */
    private Orders convertOrders(String whseid,ApiOrders o,ApiMappingInfoBo config) {
        //获取wms单号
        //String orderkey = commonService.getWmsKey(o.getWhseid(),"S", "ORDER");
        String orderkey = commonService.getWmsKey(whseid, SysNumberType.SysNumberType3);
        Orders orders = createOrders(config);
        BeanUtils.copyProperties(o,orders,"serialkey","details");
        orders.setOrderkey(orderkey);
        orders.setStatus("02");
        orders.setPrintdate(o.getPrintdata());
        orders.setRtxcarriercode(o.getCarriercode());
        orders.setOrderdate(LocalDateTime.now());
        Double totalQty = 0D;
       
        int line = 1;
        List<Orderdetail> details = new ArrayList<>();
        for(ApiOrderdetail od : o.getDetails()){
            Orderdetail detail = createOrderdetail(config);
            BeanUtils.copyProperties(od,detail,"serialkey");
            detail.setRtxexternorderkey2(o.getRtxexternorderkey2());
            detail.setOrderkey(orderkey);
            detail.setStatus("02");
            detail.setOpenqty(detail.getOriginalqty());
            detail.setOrderlinenumber(String.format("%05d",line++));
            detail.setSkurotation("Lottable04");
            details.add(detail);
            Sku sku = ordersValidation.validationSku(whseid, detail.getStorerkey(), detail.getSku(), true);
            detail.setAllocatestrategykey(sku.getStrategykey());
            totalQty += od.getOriginalqty();
        }
        orders.setRtxbCounty(o.getRtxcCounty());
        orders.setTotalqty(new BigDecimal(totalQty));
        orders.setOpenqty(orders.getTotalqty());
        orders.setDetails(details);
        return orders;
    }
    
    public Orders createOrders(ApiMappingInfoBo config){
    	Orders head = null;
    	try {
    		Long apiid =  config.getTargetApi().getId();
    		Map<String,Class> map = ClassHolder.apiconfigClassMap.get(apiid+"");
    		if(map != null) {
    			Class headclass =map.get("main_link");
    			head = (Orders) headclass.newInstance();
    		}else {
    			head = new Orders();
    		}
    	} catch (Exception e) {
    		head = new Orders();
    	}

    	return head;
    }
    
    public Orderdetail createOrderdetail(ApiMappingInfoBo config){
    	Orderdetail head = null;
    	try {
    		Long apiid =  config.getTargetApi().getId();
    		Map<String,Class> map = ClassHolder.apiconfigClassMap.get(apiid+"");
    		if(map != null) {
    			Class headclass =map.get("sub_link");
    			head = (Orderdetail) headclass.newInstance();
    		}else {
    			head = new Orderdetail();
    		}
    	} catch (Exception e) {
    		head = new Orderdetail();
    	}

    	return head;
    }
    
    /**
     * 匹配系统代码CarrierMatching配置的承运商
     * 匹配不到则取原本承运商
     * @param o
     */
    private void carriercodeMapping(String whseid,Orders orders,String carriercode) {
    	orders.setRtxcarriercode(carriercode);
        LambdaQueryWrapper<Codelkup> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(Codelkup::getListname, "CarrierMatching")
        		.eq(Codelkup::getUdf5, orders.getStorerkey());
        List<Codelkup> carrierMatchingList = commonService.selectCodelkupByWrapper(whseid, wrapper);
        String carriercode1 = Optional.ofNullable(carriercode).orElse("");
        for(Codelkup config:carrierMatchingList) {
        	if(carriercode1.equals(config.getUdf3())){
        		carriercode1 = config.getUdf4();
        	}
        }
        orders.setCarriercode(carriercode1);
      
    }
}
